/**
 * DSP Base
 * Copyright 2015 Baidu Inc. All rights reserved.
 *
 * @file 通用工具方法
 * @exports playmall.util
 * @author maoquan
 */

define(
    function (require) {

        var eoo = require('eoo');
        var u = require('underscore');
        var ubRiaUtil = require('ub-ria/util');

        /**
         * 工具对象
         *
         * @namespace dsp-base.util
         */
        var util = eoo.static(ubRiaUtil);

        /**
         * 字符串格式化
         *
         * 简单的格式化使用`${name}`进行占位
         *
         * @param {string} template 原字符串
         * @param {Object} data 用于模板替换的数据
         * @param {string} [pre] 变量前缀，默认'$'
         * @return {string} 格式化后的字符串
         */
        util.format = function (template, data, pre) {
            if (!template) {
                return '';
            }

            if (data == null) {
                return template;
            }

            pre = pre || '$';

            return template.replace(
                new RegExp('\\' + pre + '\\{(.+?)\\}', 'g'),
                function (match, key) {
                    var replacer = data[key];
                    if (typeof replacer === 'function') {
                        replacer = replacer(key);
                    }

                    return replacer == null ? '' : replacer;
                }
            );
        };

        /**
         * 通用的树节点遍历
         *
         * @param {Object|Array} node 要遍历的起始节点
         * @param {Function} func 具体操作
         */
        util.walkTree = function (node, func) {
            var walkFunc;
            if (u.isArray(node)) {
                walkFunc = walkArray;
            }
            else if (u.isObject(node)) {
                walkFunc = walkObject;
            }

            if (walkFunc) {
                var args = [].slice.call(arguments, 0);
                args.splice(1, 0, null);
                walkFunc.apply(null, args);
            }

            /**
             * 遍历object, object应有children属性
             *
             * @param {Object} node 节点
             * @param {Object|null} parent node的父节点
             * @param {Function} func 操作
             */
            function walkObject(node, parent, func) {
                var args = [].slice.call(arguments, 3);
                var result = func.apply(null, [node, parent].concat(args));
                // 如果当前节点返回false，则停止递归
                var children = node.children;
                if (result !== false && children) {
                    walkArray.apply(
                        null,
                        [children, node].concat([].slice.call(arguments, 2))
                    );
                }
            }

            /**
             * 遍历数组
             *
             * @param {Array} nodeList nodeList
             * @param {Object|null} parent node的父节点
             * @param {Function} func 操作
             */
            function walkArray(nodeList, parent, func) {
                for (var i = 0; i < nodeList.length; i++) {
                    walkObject.apply(
                        null,
                        [nodeList[i], parent].concat([].slice.call(arguments, 2))
                    );
                }
            }
        };

        /**
         * 映射数组
         *
         * @param {Array} list 数组
         * @param {Function} mapper 映射条件
         * @return {Array}
         */
        function mapList(list, mapper) {
            return u.map(
                list,
                function (node) {
                    return util.mapTree(node, mapper);
                }
            );
        }

        /**
         * 从源集合映射出新集合
         *
         * @param {Array|Object} collection 树(有无根节点均可)
         * @param {Function} mapper 映射条件
         * @return {Array|Object}
         */
        util.mapTree = function (collection, mapper) {
            if (Array.isArray(collection)) {
                collection = mapList(collection, mapper);
            }
            else if (util.isObject(collection) && collection) {
                collection = util.clone(collection);

                collection = mapper(collection);

                if (collection.children) {
                    collection.children = mapList(collection.children, mapper);
                }
            }

            return collection;
        };

        /**
         * 过滤数组
         *
         * @param {Array} list 数组
         * @param {Function} filter 过滤条件
         * @return {Array}
         */
        function filterList(list, filter) {
            var  newList = [];

            u.each(list, function (node) {
                node = filterTree(node, filter);

                if (!util.isEmpty(node)) {
                    newList.push(node);
                }
            });

            return newList;
        }

        /**
         * 过滤树
         *
         * @param {Array|Object} collection 树(有无根节点均可)
         * @param {Function} filter 过滤条件
         * @return {Array|Object}
         */
        function filterTree(collection, filter) {
            if (Array.isArray(collection)) {
                collection = filterList(collection, filter);
            }
            else if (util.isObject(collection) && collection) {
                if (collection.children && collection.children.length) {
                    collection.children = filterList(collection.children, filter);

                    if (!collection.children.length && !collection.isFilterd) {
                        collection = {};
                    }
                }
                else if (!collection.isFilterd) {
                    collection = {};
                }
            }

            return collection;
        }

        /**
         * 从树形中过滤出符合要求的指定集合
         * #Important# 每个命中节点的祖先节点都要存在
         *
         * @param {Array|Object} collection 树(有无根节点均可)
         * @param {Function} filter 过滤条件
         * @return {Array|Object}
         */
        util.filterTree = function (collection, filter) {
            // 先遍历一下树形，标识匹配的节点
            // 再遍历一下树形，筛选出匹配的节点重组树形
            // 使用这种方式，算法时间复杂度会比较低
            collection = util.mapTree(
                collection,
                function (node) {
                    node.isFilterd = filter(node);
                    return node;
                }
            );
            collection = filterTree(collection);

            return collection;
        };

        /**
         * 查找指定值节点包含的子数组
         *
         * @param {Array} list 数组
         * @param {Function} selector 查询条件
         * @return {Array}
         */
        function selectList(list, selector) {
            var  newList = [];

            u.each(list, function (node) {
                if (selector(node)) {
                    newList.push(node);
                }
                else {
                    if (node.children) {
                        newList = newList.concat(selectList(node.children, selector));
                    }
                }
            });
            return newList;
        }

        /**
         * 从树形中查找到符合要求的子树
         *
         * @param {Array|Object} collection 树(有无根节点均可)
         * @param {Function} selector 查询条件
         * @return {Array|Object}
         */
        util.selectTree = function (collection, selector) {
            if (Array.isArray(collection)) {
                return selectList(collection, selector);
            }

            if (util.isObject(collection) && collection) {
                if (selector(collection)) {
                    return collection;
                }

                if (collection.children && collection.children.length) {
                    return selectList(collection.children, selector);
                }
            }

            return {};
        };

        return util;
    }
);
